# Software Requirements Specification
## RVC Controller Software

---

| 항목 | 내용 |
|------|------|
| 문서 번호 | RVC-SRS-001 |
| 버전 | v2.0 |
| 작성일 | 2026-05-21 |
| 작성자 | OOAD Team 9 |
| 표준 준거 | IEEE Std 830-1998 |
| 상태 | Released |

---

## 변경 이력 (Revision History)

| 버전 | 날짜 | 변경 내용 | 작성자 |
|------|------|-----------|--------|
| v1.0 | 2026-05-20 | 최초 작성 — 비표준 구조 | OOAD Team 9 |
| v2.0 | 2026-05-21 | IEEE Std 830-1998 구조로 전면 재작성, 시스템 테스트 7개로 갱신 | OOAD Team 9 |

---

## 목차 (Table of Contents)

1. [서론 (Introduction)](#1-서론-introduction)
   - 1.1 목적 (Purpose)
   - 1.2 범위 (Scope)
   - 1.3 정의, 약어, 약자 (Definitions, Acronyms, and Abbreviations)
   - 1.4 참조 문서 (References)
   - 1.5 문서 구성 (Overview)
2. [전체 설명 (Overall Description)](#2-전체-설명-overall-description)
   - 2.1 제품 관점 (Product Perspective)
   - 2.2 제품 기능 (Product Functions)
   - 2.3 사용자 특성 (User Characteristics)
   - 2.4 제약사항 (Constraints)
   - 2.5 가정 및 의존성 (Assumptions and Dependencies)
3. [세부 요구사항 (Specific Requirements)](#3-세부-요구사항-specific-requirements)
   - 3.1 외부 인터페이스 요구사항 (External Interface Requirements)
   - 3.2 기능 요구사항 (Functional Requirements)
   - 3.3 성능 요구사항 (Performance Requirements)
   - 3.4 설계 제약 (Design Constraints)
   - 3.5 소프트웨어 시스템 속성 (Software System Attributes)
4. [부록 (Appendices)](#4-부록-appendices)
   - Appendix A: 추적 매트릭스 (Traceability Matrix)
   - Appendix B: 검증 요구사항 (Verification Requirements)

---

## 1. 서론 (Introduction)

### 1.1 목적 (Purpose)

본 문서는 RVC(Robot Vacuum Cleaner) Controller Software의 소프트웨어 요구사항 명세서(SRS)이다. 시스템이 **무엇을(what)** 수행해야 하는지를 정의하며, 개발자, 테스터, 프로젝트 이해관계자를 주요 독자로 한다.

본 SRS는 구현 완료 시점을 기준으로 작성된 **As-Built SRS**로서, 구현된 기능 요구사항(FR), 비기능 요구사항(NFR), 외부 인터페이스, 설계 제약, 검증 기준을 포괄한다.

### 1.2 범위 (Scope)

**제품명:** RVC Controller Software  
**제품 식별자:** RVC-SW-001

RVC Controller Software는 로봇 청소기의 핵심 제어 논리를 담당한다. 센서 데이터를 읽어 이동 유닛 및 청소 유닛을 제어하며, 장애물 회피, 먼지 감지·청소 파워 제어, 센서 오류 처리 기능을 제공한다.

**포함 범위 (In Scope):**

| 항목 | 설명 |
|------|------|
| Controller SW 핵심 로직 | 이동·청소·센서·오류 처리 (UC-01 ~ UC-08) |
| HW 추상화 인터페이스 | `Sensor`, `MovementUnit`, `CleaningUnit` 순수 가상 클래스 |
| 대화형 Simulator | CLI 기반 HW-free 전체 스택 실행 도구 |
| CI/CD 파이프라인 | GitHub Actions 기반 빌드·테스트·정적 분석 |

**제외 범위 (Out of Scope):**

| 항목 | 이유 |
|------|------|
| 실제 HW 드라이버 구현 | HW 추상화 인터페이스만 정의 |
| 모바일 앱·네트워크 통신 | 별도 시스템 |
| 지도 생성·경로 계획 알고리즘 | 미래 확장 영역 |

### 1.3 정의, 약어, 약자 (Definitions, Acronyms, and Abbreviations)

| 용어 | 정의 |
|------|------|
| RVC | Robot Vacuum Cleaner. 자동 청소 로봇 |
| Controller | RVC 핵심 제어 클래스. 센서 입력을 받아 MovementUnit과 CleaningUnit을 제어 |
| MovementUnit | RVC 이동을 담당하는 HW 추상화 인터페이스 |
| CleaningUnit | 흡입·걸레질을 담당하는 HW 추상화 인터페이스 |
| ObstacleSensor | 장애물 감지 센서 HW 추상화 인터페이스 |
| DustSensor | 먼지 감지 센서 HW 추상화 인터페이스 |
| RVCSimulator | Sim 컴포넌트로 전체 SW 스택을 구성한 HW-free 테스트 도구 |
| pollSensors() | HW 타이머 1 사이클에 해당하는 Controller의 센서 폴링 메서드 |
| tick | Simulator에서 `pollSensors()`를 1회 실행하는 조작 단위 |
| kDustThreshold | 청소 파워 부스트 발동 먼지 임계값 (0.5; 범위 0.0~1.0) |
| kErrorThreshold | 영구 센서 오류 판정에 필요한 누적 오류 횟수 (3회) |
| DI | Dependency Injection. 의존성 주입 |
| DIP | Dependency Inversion Principle. 의존성 역전 원칙 |
| OCP | Open-Closed Principle. 개방-폐쇄 원칙 |
| FR | Functional Requirement. 기능 요구사항 |
| NFR | Non-Functional Requirement. 비기능 요구사항 |
| UC | Use Case. 유스케이스 |
| SRS | Software Requirements Specification. 소프트웨어 요구사항 명세서 |
| SDD | Software Design Document. 소프트웨어 설계 문서 |
| CI | Continuous Integration. 지속적 통합 |

### 1.4 참조 문서 (References)

| 문서 번호 | 문서명 | 버전 | 위치 |
|-----------|--------|------|------|
| IEEE Std 830-1998 | IEEE Recommended Practice for Software Requirements Specifications | 1998 | IEEE Standards |
| RVC-REQ-001 | Requirements Specification | v1.1 | `docs/requirements.md` |
| RVC-UC-001 | Use Case Specification | v1.0 | `docs/use_cases.md` |
| RVC-SDD-001 | Software Design Document | v1.0 | `docs/SDD.md` |
| RVC-CD-001 | Design Class Diagram | v1.0 | `docs/class_diagram.md` |
| RVC-SD-001 | Sequence Diagrams (Design Level) | v1.2 | `docs/sequence_diagram.md` |
| RVC-SSD-001 | System Sequence Diagram | v1.0 | `docs/system_sequence_diagram.md` |

### 1.5 문서 구성 (Overview)

본 SRS는 IEEE Std 830-1998에 정의된 권장 구조를 따른다.

- **Section 2 (전체 설명):** 시스템 맥락, 상위 기능 목록, 사용자 특성, 운영 환경 제약, 가정을 기술한다.
- **Section 3 (세부 요구사항):** 외부 인터페이스, 기능 요구사항, 성능 요구사항, 설계 제약, 소프트웨어 품질 속성을 상세히 기술한다. 모든 기능 요구사항은 "shall"(필수) 또는 "should"(권장)로 표현된다.
- **Appendix A (추적 매트릭스):** FR ↔ UC ↔ 구현 메서드 ↔ 테스트 케이스 간 추적 관계를 제공한다.
- **Appendix B (검증 요구사항):** 단위·통합·시스템 테스트 목록과 각 테스트의 검증 항목을 정의한다.

---

## 2. 전체 설명 (Overall Description)

### 2.1 제품 관점 (Product Perspective)

#### 2.1.1 시스템 맥락 (System Context)

RVC Controller Software는 더 큰 RVC 하드웨어 시스템의 일부로 동작한다. 본 SW는 독립적인 새로운 제품이 아니며, 기존 RVC 하드웨어 플랫폼 위에서 동작하는 제어 소프트웨어이다.

```
┌──────────────────────────────────────────────────────────────┐
│                        RVC System                            │
│                                                              │
│   ┌────────┐    ┌────────────┐    ┌──────────────────────┐   │
│   │  RVC   │───▶│ Controller │───▶│   MovementUnit (IF)  │   │
│   │(Facade)│    │            │───▶│   CleaningUnit (IF)  │   │
│   └────────┘    │            │◀───│   ObstacleSensor (IF)│   │
│                 └────────────┘◀───│   DustSensor (IF)    │   │
│                                   └──────────────────────┘   │
│                                            │ HW Abstraction  │
└────────────────────────────────────────────┼─────────────────┘
                                             ▼
                                   [Physical Hardware]
                              (Motor, IR Sensor, Dust Sensor)
```

#### 2.1.2 시스템 인터페이스 (System Interfaces)

Controller는 네 가지 HW 추상화 인터페이스를 통해서만 하드웨어와 통신한다. 구체적인 HW 구현체는 런타임에 Dependency Injection으로 제공된다.

| 인터페이스 | 역할 | 방향 |
|-----------|------|------|
| `MovementUnit` | 전진, 후진, 정지, 회전 명령 | Controller → HW |
| `CleaningUnit` | 청소 시작, 파워 부스트, 파워 복귀 명령 | Controller → HW |
| `ObstacleSensor` | 장애물 감지 여부, 센서 위치, 상태 조회 | HW → Controller |
| `DustSensor` | 먼지 수준 조회, 먼지 감지 여부, 상태 조회 | HW → Controller |

#### 2.1.3 메모리 제약 (Memory Constraints)

Controller는 동적 메모리 할당을 최소화한다. 센서 오류 카운터는 `std::unordered_map<int, int>`로 관리되며, 센서 ID별로 독립적인 항목을 저장한다.

#### 2.1.4 운영 (Operations)

시스템은 단일 운영 모드를 갖는다:

| 모드 | 설명 | 진입 조건 |
|------|------|-----------|
| IDLE | 초기 대기 상태. 청소 미시작 | 시스템 전원 인가 |
| CLEANING | 전진하며 청소 수행 | `startCleaning()` 호출 |
| STOPPED | 장애물 감지 후 일시 정지 | 전방 장애물 감지 |
| TURNING | 방향 전환 기동 중 | 장애물 회피 로직 |
| REVERSING | 후진 기동 중 | 전방향 장애물 감지 |

### 2.2 제품 기능 (Product Functions)

본 SRS에서 다루는 주요 기능은 다음과 같다. 각 기능의 상세 요구사항은 Section 3.2에 기술한다.

| 기능 분류 | 설명 | 관련 UC |
|-----------|------|---------|
| 정상 청소 | 전진하며 지속적으로 청소 수행 | UC-01 |
| 전방 장애물 감지 | 전방 센서 데이터 수신 및 처리 | UC-02 |
| 전방 장애물 회피 | 정지 → 측면 확인 → 회전 → 전진 재개 | UC-03 |
| 측면 장애물 감지 | 좌·우 센서 데이터 수신 및 방향 결정 지원 | UC-04 |
| 전방향 장애물 회피 | 후진 → 회전 → 전진 재개 | UC-05 |
| 먼지 감지 | 먼지 센서 데이터 수신 및 처리 | UC-06 |
| 청소 파워 부스트 | 고농도 먼지 구간에서 흡입력 증강 후 복귀 | UC-07 |
| 센서 오류 처리 | 일시/영구 오류 분류 및 비상 정지 | UC-08 |

### 2.3 사용자 특성 (User Characteristics)

RVC Controller SW는 완전 자율 시스템으로, 일반 사용자의 런타임 개입이 없다.

| 사용자 유형 | 특성 | 상호작용 방식 |
|------------|------|--------------|
| 최종 사용자 (가정) | 기술 지식 불필요. 전원 버튼만 조작 | HW 전원 버튼 → `startCleaning()` 트리거 |
| HW 엔지니어 | C++ 및 임베디드 지식 보유 | HW 인터페이스 구현체 작성 |
| SW 개발자 | C++17, CMake, GTest 숙달 | 소스 코드, 테스트 작성 |
| QA 엔지니어 | 테스트 도구 사용 능숙 | `rvc_sim` CLI, `ctest` 사용 |

### 2.4 제약사항 (Constraints)

#### 2.4.1 규제 정책 (Regulatory Policies)

- 안전 관련 요구사항(NFR-SAF-01, NFR-SAF-02)은 소비자 기기 안전 기준에 준한다.

#### 2.4.2 HW 제한 (Hardware Limitations)

- Controller는 직접 HW 레지스터에 접근하지 않으며, 반드시 추상 인터페이스(`= 0`)만 사용해야 한다.
- 인터페이스 메서드 호출의 실제 응답 시간은 HW 플랫폼에 의존하며, SW 레이어는 HW 응답을 기다리지 않는 비동기 설계를 지향한다.

#### 2.4.3 인터페이스 요구사항 (Interfaces to Other Applications)

- HW 드라이버 구현체는 반드시 `ObstacleSensor`, `DustSensor`, `MovementUnit`, `CleaningUnit` 추상 인터페이스를 상속하여 구현해야 한다.

#### 2.4.4 병렬 운영 (Parallel Operations)

- 본 SRS 범위의 Controller는 단일 스레드 폴링 모델을 사용한다. 멀티스레드 확장은 본 SRS 범위 외이다.

#### 2.4.5 언어 요구사항 (Language Requirements)

- 구현 언어: C++17
- 빌드 시스템: CMake ≥ 3.20
- 테스트 프레임워크: Google Test / Google Mock v1.14.0

### 2.5 가정 및 의존성 (Assumptions and Dependencies)

| 항목 | 내용 |
|------|------|
| **가정 1** | HW 인터페이스 구현체는 메서드 호출 후 100ms 이내에 반환한다. |
| **가정 2** | `pollSensors()`는 외부 HW 타이머에 의해 주기적으로 호출된다 (기간: ≤ 100ms). |
| **가정 3** | 센서 값의 범위는 `ObstacleSensor`는 boolean, `DustSensor`는 0.0~1.0으로 정규화된다. |
| **가정 4** | 동일 폴링 사이클에서 전방 장애물이 감지되면 먼지 처리보다 우선 처리된다. |
| **의존성 1** | Google Test / Google Mock v1.14.0 (FetchContent로 자동 다운로드) |
| **의존성 2** | GitHub Actions Ubuntu 최신 runner (CI 환경) |

---

## 3. 세부 요구사항 (Specific Requirements)

> 요구사항 표현 규칙:
> - **shall** : 필수 요구사항 (Must)
> - **should** : 권장 요구사항 (Should)
> - 각 요구사항은 단일하고 검증 가능한(verifiable) 형태로 작성됨

### 3.1 외부 인터페이스 요구사항 (External Interface Requirements)

#### 3.1.1 사용자 인터페이스 (User Interfaces)

`SRS-UI-01`  
대화형 Simulator(`rvc_sim`)는 표준 입력(stdin)으로 명령을 수신하고 표준 출력(stdout)으로 상태를 출력하는 CLI 인터페이스를 **shall** 제공한다.

`SRS-UI-02`  
CLI는 다음 명령을 **shall** 지원한다: `start`, `tick`, `front [on|off]`, `left [on|off]`, `right [on|off]`, `dust <0.0-1.0>`, `error <id>`, `status`, `reset`, `help`, `quit`.

`SRS-UI-03`  
`status` 명령 실행 시 이동 상태(Motion), 마지막 회전 방향, 정지 횟수, 청소 활성 여부, 파워 레벨, 각 센서 값을 **shall** 출력한다.

#### 3.1.2 하드웨어 인터페이스 (Hardware Interfaces)

`SRS-HW-01`  
Controller는 `MovementUnit` 순수 가상 클래스를 통해서만 이동 HW에 접근해야 **shall** 한다. 직접 HW 레지스터 접근은 **shall not** 허용된다.

`SRS-HW-02`  
Controller는 `CleaningUnit` 순수 가상 클래스를 통해서만 청소 HW에 접근해야 **shall** 한다.

`SRS-HW-03`  
Controller는 `ObstacleSensor` 및 `DustSensor` 순수 가상 클래스를 통해서만 센서 HW 데이터를 읽어야 **shall** 한다.

`SRS-HW-04`  
모든 HW 추상화 인터페이스는 `Sensor` 기반 클래스를 상속하며, `getSensorId()` 및 `getStatus()`를 **shall** 제공한다.

#### 3.1.3 소프트웨어 인터페이스 (Software Interfaces)

`SRS-SW-01`  
`RVC` 클래스는 외부 시스템이 Controller에 접근하는 유일한 Facade 역할을 **shall** 한다.

`SRS-SW-02`  
`RVC::startCleaning()`은 `Controller::startCleaning()`을 위임 호출해야 **shall** 한다.

`SRS-SW-03`  
`Controller` 생성자는 의존성 주입(Dependency Injection) 방식으로 `MovementUnit*`, `CleaningUnit*`, `ObstacleSensor*` (3개), `DustSensor*`를 **shall** 주입받는다.

#### 3.1.4 통신 인터페이스 (Communications Interfaces)

본 SRS 범위에서 네트워크 또는 원격 통신 인터페이스는 정의되지 않는다.

---

### 3.2 기능 요구사항 (Functional Requirements)

기능 요구사항은 Use Case 단위로 구조화하였다.

---

#### 3.2.1 UC-01: 정상 청소 수행 (Perform Normal Cleaning)

**선행 조건:** 시스템이 `IDLE` 상태이다.  
**후행 조건:** 시스템이 `CLEANING` 상태이며 전진 중이다.

`SRS-FR-01-01`  
시스템은 `startCleaning()` 호출 시 `CleaningUnit::startCleaning()`을 **shall** 호출한다.

`SRS-FR-01-02`  
시스템은 `startCleaning()` 호출 시 `MovementUnit::moveForward()`를 **shall** 호출하여 전진을 시작한다.

`SRS-FR-01-03`  
시스템은 `startCleaning()` 호출 시 CleaningUnit 활성화가 이동 명령보다 **shall** 먼저 수행된다.

`SRS-FR-01-04`  
시스템은 매 폴링 사이클(`pollSensors()`)에서 장애물 또는 먼지 이벤트가 없으면 `MovementUnit::moveForward()`를 **shall** 호출하여 전진을 유지한다.

`SRS-FR-01-05`  
시스템은 매 폴링 사이클에서 전방 센서 `readData()`를 **shall** 호출한다.

---

#### 3.2.2 UC-02: 전방 장애물 감지 (Detect Front Obstacle)

**선행 조건:** 시스템이 `CLEANING` 상태이다.  
**후행 조건:** Controller가 전방 장애물 존재를 인지하고 회피 절차를 시작한다.

`SRS-FR-02-01`  
시스템은 `pollSensors()` 실행 중 전방 센서의 `isObstacleDetected()` 반환값이 `true`이면 이동을 **shall** 즉시 정지한다.

`SRS-FR-02-02`  
시스템은 전방 장애물 감지 시 `MovementUnit::stop()`을 `MovementUnit::moveForward()` 호출 이전에 **shall** 호출한다.

`SRS-FR-02-03`  
시스템은 `reportObstacle(SensorPosition::FRONT)` 호출 시 예외를 발생시키지 **shall** 않는다.

---

#### 3.2.3 UC-03: 전방 장애물 회피 (Avoid Front Obstacle)

**선행 조건:** 전방 장애물이 감지된 상태이다.  
**후행 조건:** 시스템이 새로운 방향으로 전진 중이다.

`SRS-FR-03-01`  
시스템은 전방 장애물 감지 후 좌·우 측면 센서를 **shall** 조회한다.

`SRS-FR-03-02`  
시스템은 좌측이 비어있고 우측이 막혀있으면 `MovementUnit::turn(Direction::LEFT)`를 **shall** 호출한다.

`SRS-FR-03-03`  
시스템은 우측이 비어있고 좌측이 막혀있으면 `MovementUnit::turn(Direction::RIGHT)`를 **shall** 호출한다.

`SRS-FR-03-04`  
시스템은 전방·좌·우 모두 막혀있으면 UC-05(전방향 장애물 회피)로 **shall** 에스컬레이션한다.

`SRS-FR-03-05`  
시스템은 방향 전환 완료 후 `MovementUnit::moveForward()`를 **shall** 호출하여 전진을 재개한다.

`SRS-FR-03-06`  
시스템은 회피 기동 중 좌·우 측면 센서 `readData()`를 **shall** 각각 호출한다.

---

#### 3.2.4 UC-04: 측면 장애물 감지 (Detect Side Obstacles)

**선행 조건:** 전방 장애물 회피 절차(UC-03)가 진행 중이다.  
**후행 조건:** 좌·우 장애물 상태가 Controller에 기록된다.

`SRS-FR-04-01`  
시스템은 `reportObstacle(SensorPosition::LEFT)` 호출 시 좌측 장애물 상태를 **shall** 기록하며, 이로 인한 즉시 정지는 **shall not** 발생한다.

`SRS-FR-04-02`  
시스템은 `reportObstacle(SensorPosition::RIGHT)` 호출 시 우측 장애물 상태를 **shall** 기록하며, 이로 인한 즉시 정지는 **shall not** 발생한다.

`SRS-FR-04-03`  
기록된 측면 장애물 상태는 UC-03의 회전 방향 결정에 **shall** 반영된다.

---

#### 3.2.5 UC-05: 전방향 장애물 회피 (Avoid All-Direction Obstacle)

**선행 조건:** 전방·좌·우 모두 장애물이 감지된 상태이다.  
**후행 조건:** 시스템이 새로운 방향으로 전진 중이다.

`SRS-FR-05-01`  
시스템은 전방향 장애물 감지 시 `MovementUnit::stop()`을 **shall** 호출한다.

`SRS-FR-05-02`  
시스템은 정지 후 `MovementUnit::moveBackward()`를 **shall** 호출하여 후진한다.

`SRS-FR-05-03`  
시스템은 후진 후 `MovementUnit::turn(Direction::BACK)`을 **shall** 호출한다.

`SRS-FR-05-04`  
시스템은 `turn(Direction::BACK)` 호출 후 `MovementUnit::moveForward()`를 **shall** 호출하여 전진을 재개한다.

`SRS-FR-05-05`  
전방향 회피 기동에서 `stop()` 호출은 `moveBackward()` 호출 이전에 **shall** 선행된다.

---

#### 3.2.6 UC-06: 먼지 감지 (Detect Dust)

**선행 조건:** 시스템이 `CLEANING` 상태이다.  
**후행 조건:** Controller가 현재 먼지 수준을 인지한다.

`SRS-FR-06-01`  
시스템은 매 폴링 사이클에서 먼지 센서 `readData()`를 **shall** 호출한다.

`SRS-FR-06-02`  
시스템은 `reportDust(double dustLevel)` 호출 시 해당 수준을 기록하며, 즉각적인 CleaningUnit 파워 변경을 **shall not** 야기한다.

`SRS-FR-06-03`  
시스템은 `reportDust()` 호출 시 예외를 발생시키지 **shall** 않는다.

---

#### 3.2.7 UC-07: 청소 파워 부스트 (Boost Cleaning Power)

**선행 조건:** 먼지 수준이 `kDustThreshold`를 초과한다.  
**후행 조건:** 청소 파워가 부스트된 후 즉시 기본값으로 복귀한다.

`SRS-FR-07-01`  
시스템은 `pollSensors()` 실행 중 `DustSensor::getDustLevel()` 반환값이 `kDustThreshold`(0.5)를 초과하면 `CleaningUnit::boostPower()`를 **shall** 호출한다.

`SRS-FR-07-02`  
시스템은 `CleaningUnit::boostPower()` 호출 직후 `CleaningUnit::restoreNormalPower()`를 **shall** 호출한다.

`SRS-FR-07-03`  
시스템은 먼지 수준이 `kDustThreshold` 이하이면 `CleaningUnit::boostPower()`를 **shall not** 호출한다.

`SRS-FR-07-04`  
시스템은 전방 장애물이 감지된 폴링 사이클에서는 먼지 부스트를 **shall not** 수행한다. (장애물 처리가 우선)

---

#### 3.2.8 UC-08: 센서 오류 처리 (Handle Sensor Error)

**선행 조건:** 센서에서 오류 값이 수신된다.  
**후행 조건:** 오류 횟수에 따라 이전 유효 상태 유지 또는 비상 정지 발생.

`SRS-FR-08-01`  
시스템은 특정 센서의 누적 오류 횟수가 `kErrorThreshold`(3) 미만이면 이전 유효 상태를 **shall** 유지하고 이동을 정지하지 **shall not** 않는다.

`SRS-FR-08-02`  
시스템은 특정 센서의 누적 오류 횟수가 `kErrorThreshold`(3) 이상이면 `MovementUnit::stop()`을 **shall** 호출하여 비상 정지한다.

`SRS-FR-08-03`  
오류 카운터는 센서 ID별로 독립적으로 **shall** 관리된다. 센서 A의 오류가 센서 B의 카운터에 영향을 미쳐서는 **shall not** 안 된다.

`SRS-FR-08-04`  
시스템은 `reportSensorError(int sensorId)` 호출 시 예외를 발생시키지 **shall** 않는다.

---

#### 3.2.9 Simulator 기능 요구사항

`SRS-FR-09-01`  
Simulator는 실제 HW 없이 전체 SW 스택(`Controller`, `RVC`, Sim 컴포넌트)을 실행할 수 있어야 **shall** 한다.

`SRS-FR-09-02`  
Simulator는 전방·좌·우 장애물 상태와 먼지 수준을 런타임에 주입할 수 있어야 **shall** 한다.

`SRS-FR-09-03`  
Simulator는 센서 오류 이벤트를 센서 ID로 주입할 수 있어야 **shall** 한다.

`SRS-FR-09-04`  
Simulator의 각 `tick()`은 `Controller::pollSensors()`를 정확히 1회 **shall** 호출한다.

`SRS-FR-09-05`  
Simulator는 `SimMovementUnit`을 통해 이동 상태(`Motion`), 마지막 회전 방향(`Direction`), 정지 횟수를 검사할 수 있어야 **shall** 한다.

`SRS-FR-09-06`  
Simulator는 `SimCleaningUnit`을 통해 청소 활성 여부, 파워 레벨, 해당 사이클의 부스트 발생 여부를 검사할 수 있어야 **shall** 한다.

---

### 3.3 성능 요구사항 (Performance Requirements)

`SRS-NFR-PER-01`  
시스템은 센서 입력 감지 후 제어 명령 출력까지의 SW 처리 응답 시간이 100ms 이하이어야 **shall** 한다.

`SRS-NFR-PER-02`  
시스템은 먼지 감지 후 청소 파워 변경 명령 발행까지의 지연이 50ms 이내이어야 **shall** 한다.

`SRS-NFR-PER-03`  
`Controller::pollSensors()`는 초당 최소 10회 이상 호출 가능한 실행 시간을 **shall** 가져야 한다. (즉, 단일 실행 시간 ≤ 100ms)

---

### 3.4 설계 제약 (Design Constraints)

#### 3.4.1 표준 준수 (Standards Compliance)

`SRS-DC-01`  
소스 코드는 C++17 표준을 **shall** 준수한다.

`SRS-DC-02`  
정적 분석 도구(clang-tidy, cppcheck)에서 오류 또는 경고가 발생하면 CI 빌드가 **shall** 실패한다 (`WarningsAsErrors: '*'`).

#### 3.4.2 아키텍처 제약 (Architectural Constraints)

`SRS-DC-03`  
모든 HW 접근은 순수 가상 클래스(`= 0`) 인터페이스를 통해서만 **shall** 이루어진다. Controller 내에서 직접 HW 타입을 참조해서는 **shall not** 안 된다.

`SRS-DC-04`  
Controller는 의존하는 모든 인터페이스(MovementUnit, CleaningUnit, 센서 4개)를 생성자 인수로 **shall** 주입받는다 (Constructor Injection).

`SRS-DC-05`  
Controller는 주입받은 포인터의 소유권을 갖지 **shall not** 않는다 (Non-owning raw pointer 사용).

#### 3.4.3 이름 규칙 (Naming Conventions)

`SRS-DC-06`  
소스 코드는 다음 이름 규칙을 **shall** 준수한다:

| 대상 | 규칙 |
|------|------|
| 클래스·구조체 | `CamelCase` |
| 메서드·함수·지역 변수·매개변수 | `camelBack` (lowerCamelCase) |
| private 멤버 변수 | `camelBack` + suffix `_` |
| Enum 상수 | `UPPER_CASE` |
| `static constexpr` 상수 | `CamelCase` + prefix `k` |
| 생산 코드 네임스페이스 | `rvc` |
| Simulator 코드 네임스페이스 | `rvc::sim` |
| 테스트 Mock 네임스페이스 | `rvc::test` |

#### 3.4.4 코드 품질 제약

`SRS-DC-07`  
모든 non-void 가상 getter 메서드에는 `[[nodiscard]]` 속성을 **shall** 적용한다.

`SRS-DC-08`  
모든 열거형(`enum class`)은 `std::uint8_t` 기반 타입을 **shall** 사용한다.

---

### 3.5 소프트웨어 시스템 속성 (Software System Attributes)

#### 3.5.1 신뢰성 (Reliability)

`SRS-NFR-REL-01`  
시스템은 특정 센서의 오류가 `kErrorThreshold`(3)회 이상 누적되면 **shall** 즉시 비상 정지한다.

`SRS-NFR-REL-02`  
시스템은 SW 오류로 인한 비정상 종료 없이 연속 8시간 이상 운영 가능해야 **should** 한다.

`SRS-NFR-REL-03`  
장애물 감지 실패율은 1% 미만이어야 **should** 한다.

#### 3.5.2 가용성 (Availability)

`SRS-NFR-AVL-01`  
비상 정지 상태(`STOPPED`)에서 청소 유닛은 계속 활성 상태를 유지해야 **shall** 한다. (이동 정지가 청소 중단을 의미하지 않는다)

#### 3.5.3 보안 (Security)

본 SRS 범위에서 네트워크 연결이 없으므로 사이버 보안 요구사항은 정의되지 않는다.

#### 3.5.4 유지보수성 (Maintainability)

`SRS-NFR-MNT-01`  
`kDustThreshold` 및 `kErrorThreshold` 임계값은 Controller 헤더 파일의 `static constexpr` 단일 지점에서 **shall** 정의되며, 코드 한 곳만 변경하여 조정 가능해야 한다.

`SRS-NFR-MNT-02`  
각 기능 모듈(MovementUnit, CleaningUnit, Sensor 구현체)은 독립적으로 수정·교체 가능하도록 **should** 설계되어야 한다.

`SRS-NFR-MNT-03`  
CI 파이프라인(GitHub Actions)에서 정적 분석 경고가 1건이라도 발생하면 빌드가 **shall** 실패한다.

#### 3.5.5 이식성 (Portability)

`SRS-NFR-PRT-01`  
Controller 핵심 로직은 특정 HW 플랫폼에 **shall not** 종속되어야 한다. 컴파일 시점에 HW 구체 타입을 참조해서는 안 된다.

`SRS-NFR-PRT-02`  
HW 제어는 추상화된 인터페이스 포인터를 통해서만 **shall** 접근한다.

#### 3.5.6 테스트 가능성 (Testability)

`SRS-NFR-TST-01`  
모든 기능 요구사항(SRS-FR-xx)은 자동화 테스트로 **shall** 검증된다.

`SRS-NFR-TST-02`  
단위·통합·시스템 테스트는 HW 없이 실행 가능해야 **shall** 한다. (Mock 또는 Simulator 사용)

`SRS-NFR-TST-03`  
GitHub Actions CI 파이프라인에서 모든 테스트가 자동으로 **shall** 실행된다.

#### 3.5.7 확장성 (Extensibility)

`SRS-NFR-EXT-01`  
새로운 센서 유형을 추가할 때 기존 Controller 코드를 수정하지 **should** 않아야 한다. (`Sensor` 추상 클래스 상속만으로 추가 가능)

`SRS-NFR-EXT-02`  
Simulator에 새로운 Sim 컴포넌트를 추가할 때 `RVCSimulator` 배선(wiring) 변경만으로 **should** 통합 가능해야 한다.

#### 3.5.8 안전성 (Safety)

`SRS-NFR-SAF-01`  
전방·좌·우 모든 방향에 장애물이 있을 때 시스템은 후진 후 방향 전환을 **shall** 수행한다. 단순 정지만으로 종료해서는 안 된다.

`SRS-NFR-SAF-02`  
비정상 센서값(범위 초과, 오류 상태)이 수신될 때 시스템은 이전 유효 상태를 **shall** 유지한다.

---

## 4. 부록 (Appendices)

### Appendix A: 추적 매트릭스 (Traceability Matrix)

#### A.1 SRS-FR → Use Case → 구현 메서드

| SRS 요구사항 ID | Use Case | 구현 메서드 |
|-----------------|----------|------------|
| SRS-FR-01-01~03 | UC-01 | `Controller::startCleaning()` |
| SRS-FR-01-04~05 | UC-01 | `Controller::pollSensors()` |
| SRS-FR-02-01~03 | UC-02 | `Controller::pollSensors()`, `Controller::reportObstacle()` |
| SRS-FR-03-01~06 | UC-03 | `Controller::avoidFrontObstacle()`, `Controller::checkSideObstacles()` |
| SRS-FR-04-01~03 | UC-04 | `Controller::recordObstacleDetection()` |
| SRS-FR-05-01~05 | UC-05 | `Controller::avoidAllDirectionObstacle()` |
| SRS-FR-06-01~03 | UC-06 | `Controller::pollSensors()`, `Controller::reportDust()` |
| SRS-FR-07-01~04 | UC-07 | `Controller::boostCleaningPower()` |
| SRS-FR-08-01~04 | UC-08 | `Controller::validateSensorData()`, `Controller::retainLastValidState()` |
| SRS-FR-09-01~06 | — | `RVCSimulator`, `SimMovementUnit`, `SimCleaningUnit` |

#### A.2 Use Case → 테스트 케이스

| Use Case | 단위 테스트 | 통합 테스트 | 시스템 테스트 |
|----------|------------|-------------|--------------|
| UC-01 | TC-UC01-001~004 | Scenario1, Scenario6 | Scenario1, Scenario7 |
| UC-02 | TC-UC02-001~003 | Scenario2 | Scenario2, Scenario7 |
| UC-03 | TC-UC03-001~004 | Scenario2 | Scenario2, Scenario3, Scenario7 |
| UC-04 | TC-UC04-001~003 | Scenario2 | Scenario2 |
| UC-05 | TC-UC05-001~002 | Scenario3 | Scenario3, Scenario7 |
| UC-06 | TC-UC06-001~003 | Scenario4 | Scenario4, Scenario5, Scenario7 |
| UC-07 | TC-UC07-001~004 | Scenario4, Scenario6 | Scenario4, Scenario5, Scenario7 |
| UC-08 | TC-UC08-001~004 | Scenario5 | Scenario6, Scenario7 |

#### A.3 NFR → 검증 방법

| NFR 요구사항 ID | 검증 방법 |
|-----------------|-----------|
| SRS-NFR-PER-01~03 | Simulator `tick()` 단위 실행 시간 측정 |
| SRS-NFR-REL-01 | TC-UC08-002, IntScenario5, SysScenario6~7 자동 테스트 |
| SRS-NFR-MNT-01 | `Controller.hpp` 내 `static constexpr` 단일 정의 코드 검토 |
| SRS-NFR-MNT-03 | GitHub Actions CI — `WarningsAsErrors: '*'` 빌드 로그 |
| SRS-NFR-PRT-01~02 | clang-tidy `readability-qualified-auto` + 코드 검토 |
| SRS-NFR-SAF-01 | TC-UC05-001, IntScenario3, SysScenario3 자동 테스트 |
| SRS-NFR-SAF-02 | TC-UC08-001, IntScenario5, SysScenario6 자동 테스트 |
| SRS-NFR-TST-01~03 | GitHub Actions `ctest` 51개 자동 실행 |
| SRS-NFR-EXT-01 | `Sensor` 추상 클래스 상속 구조 코드 검토 |
| SRS-DC-02~08 | CI clang-tidy + cppcheck 자동 검사 |

---

### Appendix B: 검증 요구사항 (Verification Requirements)

#### B.1 단위 테스트 (Unit Tests)

**테스트 파일:** `rvc_project/tests/unit/ControllerTest.cpp`, `tests/unit/SensorTest.cpp`  
**테스트 수:** 38개 (인터페이스 계약 11 + UC별 단위 27)  
**도구:** Google Test, Google Mock (`NiceMock<T>`)

| 테스트 ID | 테스트명 | 검증 항목 | 관련 SRS |
|-----------|---------|-----------|---------|
| TC-UC01-001 | StartCleaning_ActivatesCleaningUnit | `startCleaning()` 호출 확인 | SRS-FR-01-01 |
| TC-UC01-002 | StartCleaning_CommandsForwardMovement | `moveForward()` 호출 확인 | SRS-FR-01-02 |
| TC-UC01-003 | PollSensors_NoObstacle_ContinuesForward | 장애물 없을 때 전진 지속 | SRS-FR-01-04 |
| TC-UC01-004 | PollSensors_ReadsAllSensorsEachCycle | 매 사이클 `readData()` 호출 | SRS-FR-01-05 |
| TC-UC02-001 | ReportFrontObstacle_TriggersStop | 전방 장애물 → `stop()` | SRS-FR-02-01 |
| TC-UC02-002 | ReportObstacle_DoesNotThrow | 예외 없이 처리 | SRS-FR-02-03 |
| TC-UC02-003 | PollSensors_FrontObstacle_StopsFirst | `stop()` → `moveForward()` 순서 | SRS-FR-02-02 |
| TC-UC03-001 | FrontObstacle_LeftFree_TurnsLeftResumesForward | 좌측 여유 → LEFT 회전 후 전진 | SRS-FR-03-02 |
| TC-UC03-002 | FrontObstacle_RightFree_TurnsRightResumesForward | 우측 여유 → RIGHT 회전 후 전진 | SRS-FR-03-03 |
| TC-UC03-003 | FrontObstacle_BothSidesBlocked_EscalatesAllDirection | 양측 막힘 → UC-05 에스컬레이션 | SRS-FR-03-04 |
| TC-UC03-004 | FrontObstacle_QueriesBothSideSensors | 좌·우 센서 모두 조회 | SRS-FR-03-06 |
| TC-UC04-001 | ReportLeftObstacle_RecordedWithoutError | 좌 장애물 기록 (정지 없음) | SRS-FR-04-01 |
| TC-UC04-002 | ReportRightObstacle_RecordedWithoutError | 우 장애물 기록 (정지 없음) | SRS-FR-04-02 |
| TC-UC04-003 | LeftObstacleRecorded_AffectsSideCheck | 기록된 좌 장애물이 방향 결정에 영향 | SRS-FR-04-03 |
| TC-UC05-001 | AllDirectionsBlocked_FullAvoidanceSequence | stop → backward → turn → forward 순서 | SRS-FR-05-01~04 |
| TC-UC05-002 | AllDirectionsBlocked_StopBeforeBackward | `stop()` → `moveBackward()` 순서 | SRS-FR-05-05 |
| TC-UC06-001 | ReportDust_RecordsWithoutError | 먼지 기록 (즉시 부스트 없음) | SRS-FR-06-02 |
| TC-UC06-002 | ZeroDustLevel_NoPowerBoost | 먼지 0 → 부스트 없음 | SRS-FR-07-03 |
| TC-UC06-003 | PollSensors_ReadsDustSensorEachCycle | 매 사이클 먼지 센서 `readData()` | SRS-FR-06-01 |
| TC-UC07-001 | HighDustLevel_TriggersPowerBoost | dust > threshold → `boostPower()` | SRS-FR-07-01 |
| TC-UC07-002 | LowDustLevel_NoPowerBoost | dust ≤ threshold → 부스트 없음 | SRS-FR-07-03 |
| TC-UC07-003 | AfterBoost_PowerIsRestored | `boostPower()` → `restoreNormalPower()` | SRS-FR-07-02 |
| TC-UC07-004 | FrontObstaclePresent_BoostDoesNotPreemptAvoidance | 장애물 우선, 먼지 부스트 비활성 | SRS-FR-07-04 |
| TC-UC08-001 | TransientSensorError_MovementNotStopped | 임계값 미만 → 정지 없음 | SRS-FR-08-01 |
| TC-UC08-002 | PersistentSensorError_StopsMovement | 임계값 도달 → `stop()` | SRS-FR-08-02 |
| TC-UC08-003 | ErrorCountIsPerSensor_IndependentCounters | 센서 ID별 독립 카운터 | SRS-FR-08-03 |
| TC-UC08-004 | ReportSensorError_DoesNotThrow | 예외 없이 처리 | SRS-FR-08-04 |

#### B.2 통합 테스트 (Integration Tests)

**테스트 파일:** `rvc_project/tests/integration/RVCSystemTest.cpp`  
**테스트 수:** 6개  
**도구:** Google Test, Google Mock (`NiceMock<T>`, `InSequence`)

| 테스트 ID | 시나리오 | 검증 항목 |
|-----------|---------|-----------|
| IntScenario1 | 정상 청소 시작 + 1 폴링 사이클 | CU 활성화 → MU 전진 순서 검증 |
| IntScenario2 | 전방 장애물 → 회피 → 전진 재개 | stop → turn LEFT → forward 호출 순서 |
| IntScenario3 | 전방향 막힘 → 완전 역전 기동 | stop → backward → turn(BACK) → forward 순서 |
| IntScenario4 | 먼지 감지 → 파워 부스트 → 복귀 | `boostPower` → `restoreNormalPower` 순서 |
| IntScenario5 | 센서 오류 일시적 → 영구 | 임계값 미만: 정지 없음 / 임계값 도달: 정지 |
| IntScenario6 | 정상 청소 + 먼지 부스트 복합 | 폴링 사이클별 부스트 발동·미발동 |

#### B.3 시스템 테스트 (System Tests)

**테스트 파일:** `rvc_project/tests/system/RVCSimulatorTest.cpp`  
**테스트 수:** 7개  
**도구:** Google Test + `RVCSimulator` (Mock 없음 — 실제 상태 변화 검증)

| 테스트 ID | 시나리오 | 검증 포인트 |
|-----------|---------|------------|
| SysScenario1 | 정상 청소 세션 — 5틱 전진 | 5틱 내내 FORWARD, 청소 활성, 부스트·정지 없음 |
| SysScenario2 | 연속 장애물 회피 — 좌·우 각 1회 | 1차: LEFT 회전, 2차: RIGHT 회전, 각 회피 후 전진 재개 |
| SysScenario3 | 사방 막힘 탈출 — 완전 역전 기동 | FORWARD 재개, `getLastTurn()==BACK`, `stopCount ≥ 2` |
| SysScenario4 | 먼지 구역 통과 — 부스트 4회 | 깨끗한 구역 부스트 0회, 먼지 구역 4회, 이후 0회 |
| SysScenario5 | 장애물+먼지 복합 — 장애물 우선 | 장애물+먼지 틱: 부스트 없음 / 장애물 해제 틱: 부스트 발동 |
| SysScenario6 | 센서 오류 누적 → 비상 정지 | 오류 1·2회: NOT STOPPED / 오류 3회: STOPPED |
| SysScenario7 | 전체 청소 세션 — 모든 UC 연속 | Phase 1~8 순차 검증 (전진→회피→먼지부스트→역전→비상정지) |

#### B.4 테스트 요약

| 테스트 계층 | 파일 | 테스트 수 | 도구 |
|-----------|------|----------|------|
| 단위 (Unit) | `ControllerTest.cpp` + `SensorTest.cpp` | 38 | GTest + GMock |
| 통합 (Integration) | `RVCSystemTest.cpp` | 6 | GTest + GMock |
| 시스템 (System) | `RVCSimulatorTest.cpp` | 7 | GTest + Simulator |
| **합계** | | **51** | |

#### B.5 빌드 및 테스트 실행

```powershell
# 빌드
cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=g++
cmake --build build --parallel 4

# 전체 51개 테스트 실행
cd build && ctest --output-on-failure

# 대화형 Simulator 실행
src/rvc_sim.exe
```